package com.game.modular.game.playerAssets.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.game.modular.gameCore.cultivate.domain.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 游戏账户武将数据
 *
 * @author cxy
 * @since 2024-08-07 19:29:35
 */
@Slf4j
@ApiModel("游戏账户武将数据")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
@SuppressWarnings("serial")
public class PlayerHero extends Model<PlayerHero> {// swagger2,mybatis-plus
    ///////////////////////////////////////////////////////////////////////////////////////////////////////// 生成实体字段
    @TableId(type = IdType.AUTO)
    @ApiModelProperty("主键")
    private Long id;

    @NotNull
    @ApiModelProperty("账号uid")
    private Long uid;

    @ApiModelProperty("武将id")
    private Long coreHeroId;

    @ApiModelProperty("玩家命名")
    private String name;

    @ApiModelProperty("等级")
    private Integer level;

    @ApiModelProperty("当前经验")
    private Long currentExp;

    @ApiModelProperty("升级所需经验")
    private Long nextExp;

    @ApiModelProperty("武力")
    private Double att;

    @ApiModelProperty("防御")
    private Double def;

    @ApiModelProperty("智力")
    private Double magic;

    @ApiModelProperty("先攻值")
    private Double speed;

    @ApiModelProperty("统帅")
    private Double des;

    @ApiModelProperty("当前兵力")
    private Long currentForce;

    @ApiModelProperty("0:防守,1:进攻")
    private Integer rankCamp;

    @ApiModelProperty("所处队伍的顺序")//("武将防守位置 1 前锋 2 中军 3 大营")
    private Integer rankOrder;

    @ApiModelProperty("装备卡槽1")
    private Long equipSlot1;

    @ApiModelProperty("装备卡槽2")
    private Long equipSlot2;

    @ApiModelProperty("天赋技能信息")
    private Long skill;

    @ApiModelProperty("技能卡槽1")
    private Long skillSlot1;

    @ApiModelProperty("技能卡槽2")
    private Long skillSlot2;

    @ApiModelProperty("星阶")
    private Integer star;
    ///////////////////////////////////////////////////////////////////////////////////////////////////////// 序列化版本号
    @TableField(exist = false)
    private static final long serialVersionUID = 437850302065134008L;


    /////////////////////////////////////////////////////////////////////////////////////////////////////////// 获取主键值
    @Override
    public Serializable pkVal() {
        return this.getId();
    }

    @TableField(exist = false)
    @ApiModelProperty("武将信息")
    private CoreHero coreHero;
    @TableField(exist = false)
    @ApiModelProperty("武将天赋技能")
    private CoreSkill coreSkill;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////    领域业务
    //////////////////////////////////////////////////////////////////////////////////////////////// 武将培养

    /**
     * 武将升星
     *
     * @param accountHero
     * @param coreHero
     * @param coreHeroStar
     * @return
     */
    public static PlayerHero risingStar(
            @NotNull(message = "武将不能为空") PlayerHero accountHero,
            @NotNull(message = "武将不能为空") CoreHero coreHero,
            @NotNull(message = "武将星级不能为空") CoreHeroStar coreHeroStar
    ) {
        // 升星
        accountHero.setStar(accountHero.getStar() + 1);
        // 重新计算属性  基础+成长x等级
        recalculateAttributes(accountHero, coreHero, coreHeroStar);
        return accountHero;
    }

    public static PlayerHero equip(
            @NotNull(message = "武将不能为空") PlayerHero playerHero,
            @NotNull(message = "背包不能为空") PlayerBag playerBag
    ) {
        CoreProp equip = playerBag.getCoreProp();
        if (equip != null) {
            playerHero.setAtt(playerHero.getAtt() + equip.getAttack());
            playerHero.setDef(playerHero.getDef() + equip.getDefense());
            playerHero.setMagic(playerHero.getMagic() + equip.getMagic());
            playerHero.setSpeed(playerHero.getSpeed() + equip.getSpeed());
            playerHero.setDes(playerHero.getDes() + equip.getCommand());
            //
            Integer type = equip.getType();
            if (type == 4) {
                playerHero.setEquipSlot1(playerBag.getId());
            }
            if (type == 5) {
                playerHero.setEquipSlot2(playerBag.getId());
            }
        }
        return playerHero;
    }

    public static PlayerHero unEquip(
            @NotNull(message = "武将不能为空") PlayerHero playerHero,
            @NotNull(message = "背包不能为空") PlayerBag playerBag
    ) {
        CoreProp equip = playerBag.getCoreProp();
        if (equip != null) {
            playerHero.setAtt(playerHero.getAtt() - equip.getAttack());
            playerHero.setDef(playerHero.getDef() - equip.getDefense());
            playerHero.setMagic(playerHero.getMagic() - equip.getMagic());
            playerHero.setSpeed(playerHero.getSpeed() - equip.getSpeed());
            playerHero.setDes(playerHero.getDes() - equip.getCommand());
            Integer type = equip.getType();
            if (type == 4) {
                playerHero.setEquipSlot1(0L);
            }
            if (type == 5) {
                playerHero.setEquipSlot2(0L);
            }
        }
        return playerHero;
    }

    public static PlayerHero upgrade(
            @NotNull(message = "武将不能为空") PlayerHero accountWuJiang,
            @NotNull(message = "武将不能为空") CoreHero coreWuJiang,
            @NotNull(message = "武将星级不能为空") CoreHeroStar coreHeroStar,
            @NotNull(message = "经验不能为空") CoreExperience coreExperience
    ) {
        Integer targetLevel = accountWuJiang.getLevel();
        if (targetLevel + 1 != coreExperience.getLevel()) {
            throw new RuntimeException("升级等级错误");
        }
        if (accountWuJiang.getCurrentExp() < accountWuJiang.getNextExp()) {
            throw new RuntimeException("经验不足");
        }
        accountWuJiang.setCurrentExp(accountWuJiang.getCurrentExp() - accountWuJiang.getNextExp());
        accountWuJiang.setLevel(accountWuJiang.getLevel() + 1);
        accountWuJiang.setNextExp(coreExperience.getExp());
        // 重新计算属性
        recalculateAttributes(accountWuJiang, coreWuJiang, coreHeroStar);
        return accountWuJiang;
    }

    /**
     * 重新计算属性
     *
     * @param playerHero
     * @param coreHero
     * @param coreHeroStar
     */
    public static void recalculateAttributes
    (
            PlayerHero playerHero,
            CoreHero coreHero,
            CoreHeroStar coreHeroStar
    ) {
        // att
        playerHero.setAtt(coreHero.getInitAtt() + coreHeroStar.getAttGrowth() * playerHero.getLevel() / 100.0);
        // def
        playerHero.setDef(coreHero.getInitDef() + coreHeroStar.getDefGrowth() * playerHero.getLevel() / 100.0);
        // magic
        playerHero.setMagic(coreHero.getInitMagic() + coreHeroStar.getMagicGrowth() * playerHero.getLevel() / 100.0);
        // speed
        playerHero.setSpeed(coreHero.getInitSpeed() + coreHeroStar.getSpeedGrowth() * playerHero.getLevel() / 100.0);
        // des
        playerHero.setDes(coreHero.getInitCommand() + coreHeroStar.getCommandGrowth() * playerHero.getLevel() / 100.0);
    }


    // 战斗消息
    @ApiModelProperty("技能")
    @TableField(exist = false)
    private Set<Long> skillStarIds;

    public Set<Long> getSkillStarIds() {
        Set<Long> back = new HashSet<>();
        if (this.skill != null) {
            back.add(this.skill);
        } else {
            this.skill = 0L;
        }
        if (this.skillSlot1 != null) {
            back.add(this.skillSlot1);
        } else {
            this.skillSlot1 = 0L;
        }
        if (this.skillSlot2 != null) {
            back.add(this.skillSlot2);
        } else {
            this.skillSlot2 = 0L;
        }
        back.remove(0L);
        return back;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////    领域业务
    public static Long getMaxCurrentForce(PlayerHero accountWuJiang) {
        return (long) (accountWuJiang.getDes() * 32L);
    }

    public static long getHeroListForce(List<PlayerHero> attackSide) {
        return attackSide.stream().mapToLong(PlayerHero::getCurrentForce).sum();
    }

    public static Map<Integer, List<PlayerHero>> obtainBothSidesSurvivalHeroList(List<PlayerHero> flush) {
        return flush.stream().filter(item -> item.getCurrentForce() > 0).collect(Collectors.groupingBy(PlayerHero::getRankCamp));
    }

    public void clear() {
        currentForce = 0L;
        rankOrder = 0;
    }
}

